﻿using System;
using CellarDoor.Gui.Elements;

namespace CellarDoor.Gui
{
    /// <summary>
    /// 
    /// </summary>
    public class UiNavigateGraph
    {
        /// <summary>
        /// The initial node
        /// </summary>
        private UiNavigateNode root;

        /// <summary>
        /// The current node
        /// </summary>
        private UiNavigateNode current;

        /// <summary>
        /// Gets the control at current position
        /// </summary>
        public UiNavigateNode Current
        {
            get { return current; }
        }

        /// <summary>
        /// Creates a new gui navigator
        /// </summary>
        /// <param name="root"></param>
        public UiNavigateGraph(UiNavigateNode root)
        {
            if (root == null)
            {
                throw new ArgumentNullException("root");
            }

            this.root = root;
            this.current = root;
        }

        /// <summary>
        /// Goes to the left control of current control, if it has any
        /// </summary>
        /// <returns>The left control or current control</returns>
        public bool GoLeft()
        {
            if (current.Left != null)
            {
                current = current.Left;
                return true;
            }
            return false;
        }

        /// <summary>
        /// Goes to the right control of current control, if it has any
        /// </summary>
        /// <returns>The right control or current control</returns>
        public bool GoRight()
        {
            if (current.Right != null)
            {
                current = current.Right;
                return true;
            }
            return false;
        }

        /// <summary>
        /// Goes to the upper control of current control, if it has any
        /// </summary>
        /// <returns>The upper control or current control</returns>
        public bool GoUp()
        {
            if (current.Up != null)
            {
                current = current.Up;
                return true;
            }
            return false;
        }

        /// <summary>
        /// Goes to the lower control of current control, if it has any
        /// </summary>
        /// <returns>The lower control or current control</returns>
        public bool GoDown()
        {
            if (current.Down != null)
            {
                current = current.Down;
                return true;
            }
            return false;
        }

        /// <summary>
        /// Goes to initial control, so the navigator returns to initial state
        /// </summary>
        /// <returns>The initial control</returns>
        public bool GoToRoot()
        {
            current = root;
            return true;
        }

        /// <summary>
        /// Adds the passed navigatable to the left of the current one.
        /// </summary>
        /// <param name="node">The navigatable to add</param>
        /// <param name="follow">If true sets the passed navigatable as current</param>
        public void AddLeft(UiNavigateNode node, bool follow)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }

            if (current.Left != null)
            {
                current.Left.Right = node;
                node.Left = current.Left;
            }
            current.Left = node;
            node.Right = current;

            if (follow)
            {
                GoLeft();
            }
        }

        /// <summary>
        /// Adds the passed navigatable to the right of the current one.
        /// </summary>
        /// <param name="node">The navigatable to add</param>
        /// <param name="follow">If true sets the passed navigatable as current</param>
        public void AddRight(UiNavigateNode node, bool follow)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }

            if (current.Right != null)
            {
                current.Right.Left = node;
                node.Right = current.Right;
            }
            current.Right = node;
            node.Left = current;

            if (follow)
            {
                GoRight();
            }
        }

        /// <summary>
        /// Adds the passed navigatable to the top of the current one.
        /// </summary>
        /// <param name="node">The navigatable to add</param>
        /// <param name="follow">If true sets the passed navigatable as current</param>
        public void AddUp(UiNavigateNode node, bool follow)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }

            if (current.Up != null)
            {
                current.Up.Down = node;
                node.Up = current.Up;
            }
            current.Up = node;
            node.Down = current;

            if (follow)
            {
                GoUp();
            }
        }

        /// <summary>
        /// Adds the passed navigatable to the bottom of the current one.
        /// </summary>
        /// <param name="node">The navigatable to add</param>
        /// <param name="follow">If true sets the passed navigatable as current</param>
        public void AddDown(UiNavigateNode node, bool follow)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }

            if (current.Down != null)
            {
                current.Down.Up = node;
                node.Down = current.Down;
            }
            current.Down = node;
            node.Up = current;

            if (follow)
            {
                GoDown();
            }
        }
    }
}
